package OceanModel;

// This package contains the OceanModel class, which provides a framework
// with which to simulate shallow-water fluid dynamics.


import java.util.HashMap;
import processing.core.*;

public class OceanModel {

	// Parameters object containing parameter like grid spacing, ocean density, etc
	public Parameters params;

	// Object that integrates model variable derivatives forward in time
	private Integrator integrator;

	// Object that calculates model variable derivatives
	private Dynamics navierStokes;

	// Model Variables
	// Layer Thickness in metres
	GriddedVariable h;
	// Layer surface perturbation in metres
	public GriddedVariable eta;
	// Pressure acting on the layer in Pascals
	GriddedVariable press;
	// Eastward fluid velocity, in m s-1
	GriddedVariable u;
	// Northward fluid velocity, in m s-1
	public GriddedVariable v;
	// Model topography depth, in metres
	GriddedVariable depth;
	// Model Eddy diffusivity, in m2 s-1
	GriddedVariable kappa;
	  
	// HashMap to store the Model variables
	HashMap<String, GriddedVariable> variables;

	// Model time counter
	double time;

	//----------------------------------
	  
	public OceanModel(Parameters inputParams) {
		// Here we initialize the model variables
		params = inputParams;

		int nz = params.nz;
		double g = params.g;
		double f = params.f;
		double beta = params.beta;
		time = 0.;

		params.rho = new double[nz];
		params.rho[0] = 1022.;

		h = new GriddedVariable(params, 'h');
		eta = new GriddedVariable(params, 'h');
		depth = new GriddedVariable(params, 'h');
		press = new GriddedVariable(params, 'h');

		// Set the layer thickness to 4000 metres
		// Set the sea surface height eta to be a gaussian hill .1 metres high
		for (int j=0; j < h.ny; j++) {
			for (int i=0; i < h.nx; i++) {
				double x = ((i - h.nx/2)/5.);
				double y = ((j - h.ny/2)/5.);
				eta.data[0][j][i] = Math.abs(.1*Math.exp(-2.*x*x - 2.*y*y));
				h.data[0][j][i] = 4000.;
			}
		}

		u = new GriddedVariable(params, 'u');
		v = new GriddedVariable(params, 'v');

		// Set the model time step to the CFL stability criteria.
		params.dt = (double) Math.sqrt((double)(params.dx*params.dy/params.g/4000.))/6.;

		// Store all the setup variables in the variables HashMap
		variables = new HashMap<String, GriddedVariable>();

		variables.put("h", h);
		variables.put("u", u);
		variables.put("v", v);
		variables.put("eta", eta);
		variables.put("pressure", press);
		variables.put("depth", depth);

		// Create the objects used to step the model forward in time
		String[] derivativeNameArray = {"eta", "u", "v"};

		navierStokes = new simpleDynamics(params, variables, derivativeNameArray);
	    
		integrator = new AdamsBashforthIntegrator(navierStokes, variables);
	    
	} // OceanModel

	//----------------------

	public void step() {
		// Steps the model forward in time params.dt seconds.
		time += params.dt;

		integrator.step(params.dt);
	} // step

	//-------------------

}
